<template>
  <div id="dom2Image" class="bg-[#efefef]">
    <!-- 图片 -->
    <img id="png-image" src="../../assets/vue.svg" alt="Generated Image" />
    <!-- 图标 -->
    <q-icon name="image" />
    <q-icon name="download"></q-icon>
    <!-- canvas -->
    <canvas width="50" height="50" id="png-canvas"></canvas>
    <!-- svg -->
    <svg
      id="png-svg"
      width="50"
      height="50"
      viewBox="0 0 50 50"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <rect width="50" height="50" fill="url(#paint0_linear_12_102)" />
      <defs>
        <linearGradient
          id="paint0_linear_12_102"
          x1="25"
          y1="0"
          x2="25"
          y2="50"
          gradientUnits="userSpaceOnUse"
        >
          <stop stop-color="#FD0" />
          <stop offset="1" stop-color="#000" />
        </linearGradient>
      </defs>
    </svg>
    <!-- svg link -->
    <svg
      id="png-svg-link"
      width="50"
      height="50"
      viewBox="0 0 50 50"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
      <rect width="50" height="50" fill="url(#paint0_linear_12_102)" />
      <defs>
        <linearGradient
          id="paint0_linear_12_102"
          x1="25"
          y1="0"
          x2="25"
          y2="50"
          gradientUnits="userSpaceOnUse"
        >
          <stop stop-color="#FD0" />
          <stop offset="1" stop-color="#000" />
        </linearGradient>
      </defs>
    </svg>

    <!-- box-shadow -->
    <div
      id="png-box-shadow"
      class="display-[inline-block] w-[50px] h-[50px] bg-[#FD0] shadow-[0_0_10px_rgba(0,0,0,0.5)]"
    ></div>
    <!-- background-image -->
    <div
      id="png-bg-image"
      class="display-[inline-block] w-[50px] h-[50px] bg-image"
    ></div>
    <!-- border -->
    <div
      id="png-border"
      class="display-[inline-block] w-[50px] h-[50px] border-gradient"
    ></div>
    <br />
    <!-- 视频 不支持-->
    <div
      id="png-video-container"
      class="display-[inline-block] w-[150px] h-[200px]"
    >
      <video
        class="w-[150px] h-[200px]"
        id="png-video"
        src="../../assets/video.mp4"
        controls
      ></video>
    </div>
    <!-- iframe 不支持-->
    <div
      id="png-iframe-container"
      class="display-[inline-block] w-[150px] h-[200px]"
    >
    <!-- <iframe
        id="png-iframe"
        src="http://localhost:5173/home"
        frameborder="0"
      ></iframe> -->
      <!-- <iframe
        id="png-iframe"
        src="https://www.baidu.com"
        frameborder="0"
      ></iframe> -->
    </div>
    <br />
    <!-- 跨域图片 不支持 -->
    <!-- <img
      id="png-cross-origin-image"
      src="https://www.baidu.com/img/baidu_jgylogo3.gif"
      alt="Generated Image"
    /> -->
    <br />
    <!-- 跨域视频 不支持-->
    <!-- <div
      id="png-cross-origin-video-container"
      class="display-[inline-block] w-[150px] h-[200px]"
    >
      <video
        class="w-full h-full"
        id="png-cross-origin-video"
        src="https://www.baidu.com/img/baidu_jgylogo3.gif"
        controls
      ></video>
    </div> -->
  </div>

  <q-separator class="q-my-md" />

  <q-btn class="mr-1" label="snapDom" @click="snapDom" />
  <q-btn
    class="mr-1"
    color="primary"
    label="html2canvas"
    @click="() => onHtml2canvas()"
  />
  <q-btn class="mr-1" label="dom-to-image-more" @click="onDom2Image" />
  <!-- <q-btn
    class="mr-1"
    color="primary"
    label="html2canvas-download"
    @click="() => onHtml2canvas(true)"
  /> -->
  <q-btn class="mr-1" label="html-to-image" @click="onHtmlToImage" />
  <q-btn class="mr-1" label="modern-screenshot" @click="onDomToPng" />
  <q-separator class="q-my-md" />

  <div id="png-container">
    <!-- <img id="png-image" src="" alt="Generated Image" /> -->
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";
import { snapdom } from "@zumer/snapdom";
import html2canvas from "html2canvas";
import domtoimage from "dom-to-image-more";
import * as htmlToImage from "html-to-image";
import { domToPng } from "modern-screenshot";

import {
  generateThumbnail,
  generateThumbnailByDomToImageMore,
} from "../../utils/thumbnail";

onMounted(() => {
  console.log("dom2Image mounted");
  // 创建一个canvas元素
  const canvas = document.getElementById("png-canvas") as HTMLCanvasElement;
  if (canvas && canvas.getContext) {
    let ctx = canvas.getContext("2d");
    if (ctx) {
      // 画背景
      ctx.fillStyle = "#FD0";
      ctx.fillRect(0, 0, 25, 25);

      ctx.fillStyle = "rgb(55, 24, 207)";
      ctx.fillRect(25, 25, 25, 25);

      ctx.fillStyle = "rgba(106, 245,23)";
      ctx.fillRect(25, 0, 25, 25);

      ctx.fillStyle = "rgb(197, 63, 39)";
      ctx.fillRect(0, 25, 25, 25);

      // 画圈
      ctx.globalAlpha = 0.2; // 设置一下背景全局透明度为0.2
      ctx.fillStyle = "white";
      for (let index = 0; index < 6; index++) {
        ctx.beginPath();
        ctx.arc(25, 25, index * 6.5, 0, Math.PI * 2, true);
        ctx.fill();
      }
    }
  }
});

// snapDom
const snapDom1 = async () => {
  const element = document.querySelector("#dom2Image");
  if (element) {
    const png = await snapdom.toPng(element, { quality: 0.9 }); // 质量为 0.9，默认值为 0.92，质量越高，图片越清晰，但文件大小也越大。

    const container = document.querySelector("#png-container");
    if (container) {
      container.appendChild(png);
    }
    // imageData.value = dataUrl;
  }
};

// snapdom from utils
const snapDom = async () => {
  const element = document.querySelector("#dom2Image") as HTMLElement;
  if (element) {
    await generateThumbnail(element, {
      width: 400,
      height: 300,
      scale: 1,
      quality: 0.95,
    })
      .then((thumbnail: HTMLImageElement) => {
        console.log("生成缩略图成功:", thumbnail);
        const container = document.querySelector("#png-container");
        if (container) {
          container.appendChild(thumbnail);
        }
      })
      .catch((error: any) => {
        console.error("生成缩略图失败:", error);
      });
  }
};

// html2canvas
const onHtml2canvas1 = async (isDownload: boolean = false) => {
  const element = document.querySelector("#dom2Image") as HTMLElement;
  if (element) {
    await html2canvas(element as HTMLElement, {
      width: element.offsetWidth, // 设置画布的宽度
      height: element.offsetHeight, // 设置画布的高度
      scale: 2, // 处理模糊问题
    })
      .then((canvas) => {
        // 将画布转换为base64编码的图像数据
        const imageData = canvas.toDataURL("image/jpeg", 1.0);

        // 创建一个img元素
        const resultImage = document.createElement("img");
        // 将图像数据设置为resultImage的src属性
        resultImage.src = imageData;

        const container = document.querySelector("#png-container");
        if (container) {
          container.appendChild(resultImage);
        }

        if (isDownload) {
          // 可选：自动下载生成的图像
          const downloadLink = document.createElement("a");
          downloadLink.href = imageData;
          downloadLink.download = "captured-image.png";
          document.body.appendChild(downloadLink);
          downloadLink.click();
          document.body.removeChild(downloadLink);
        }
      })
      .catch((err) => {
        console.log("error caputure: ", err);
      });
  }
};

const dpr = () => {
  if (window.devicePixelRatio && window.devicePixelRatio > 1) {
    return window.devicePixelRatio;
  }
  return 1;
};

const onHtml2canvas = () => {
  // 获取想要转换的 DOM 节点
  const element = document.querySelector("#dom2Image") as HTMLElement;
  const box = window.getComputedStyle(element);
  // DOM 节点计算后宽高
  const width = parseInt(box.width, 10);
  const height = parseInt(box.height, 10);
  // 获取像素比
  const scaleBy = dpr();
  // 创建自定义 canvas 元素
  const canvas = document.createElement("canvas") as HTMLCanvasElement;
  // 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
  canvas.width = width * scaleBy;
  canvas.height = height * scaleBy;
  // 设定 canvas css宽高为 DOM 节点宽高
  canvas.style.width = `${width}px`;
  canvas.style.height = `${height}px`;
  // 获取画笔
  const context = canvas.getContext("2d") as CanvasRenderingContext2D;
  // 将所有绘制内容放大像素比倍
  context.scale(scaleBy, scaleBy);
  if (context) {
    // 将自定义 canvas 作为配置项传入，开始绘制
    html2canvas(element, { canvas }).then((imgDom) => {
      let url = imgDom.toDataURL();
      console.log(url); // 此时的url是图片的base64格式，可直接赋值到img的src上

      //   创建一个img元素
      const resultImage = document.createElement("img");
      // 将图像数据设置为resultImage的src属性
      resultImage.src = url;

      const container = document.querySelector("#png-container");
      if (container) {
        container.appendChild(resultImage);
      }
    });
  }
};

// 总结
// 1. snapDom 是一个基于 canvas 实现的截图工具，它可以将指定的 DOM 元素截图并返回一个图片对象。
// 2. html2canvas 是一个基于 canvas 实现的截图工具，它可以将指定的 DOM 元素截图并返回一个 canvas 对象。
// 缺点：
// 1. snapDom 不支持跨域图片、跨域视频、视频、iframe 等元素的截图。
// 2. html2canvas 不支持跨域图片、跨域视频、视频、iframe 等元素的截图。
// 3. snapDom 截图的图片质量较低，而 html2canvas 截图的图片质量较高。
// 4. snapDom 截图的图片大小较小，而 html2canvas 截图的图片大小较大。
// 5. snapDom 截图的图片格式为 png，而 html2canvas 截图的图片格式为 canvas。
// 6. snapDom 截图的图片不支持下载，而 html2canvas 截图的图片支持下载。

const onDom2Image1 = async () => {
  const element = document.querySelector("#dom2Image");
  if (element) {
    const png = await domtoimage.toPng(element);
    //   创建一个img元素
    const resultImage = document.createElement("img");
    // 将图像数据设置为resultImage的src属性
    resultImage.src = png;

    const container = document.querySelector("#png-container");
    if (container) {
      container.appendChild(resultImage);
    }
  }
};
const onDom2Image = async () => {
  const element = document.querySelector("#dom2Image");
  if (element) {
    generateThumbnailByDomToImageMore(element as HTMLElement, {
      width: 400,
      height: 300,
      scale: 1,
      quality: 0.95,
    })
      .then((thumbnail: HTMLImageElement) => {
        console.log("生成缩略图成功:", thumbnail);
        const container = document.querySelector("#png-container");
        if (container) {
          container.appendChild(thumbnail);
        }
      })
      .catch((error: any) => {
        console.error("生成缩略图失败:", error);
      });
  }
};

const onHtmlToImage = async () => {
  const element = document.querySelector("#dom2Image") as HTMLElement;
  if (element) {
    const png = await htmlToImage.toPng(element);
    //   创建一个img元素
    const resultImage = document.createElement("img");
    // 将图像数据设置为resultImage的src属性
    resultImage.src = png;

    const container = document.querySelector("#png-container");
    if (container) {
      container.appendChild(resultImage);
    }
  }
};

// modern-screenshot
const onDomToPng = async () => {
  const element = document.querySelector("#dom2Image");
  if (element) {
    const png = await domToPng(element);
    //   创建一个img元素
    const resultImage = document.createElement("img");
    // 将图像数据设置为resultImage的src属性
    resultImage.src = png;

    const container = document.querySelector("#png-container");
    if (container) {
      container.appendChild(resultImage);
    }
  }
};
</script>

<style scoped>
#dom2Image {
  position: relative;
}

.bg-image {
  background-image: url("../../assets/vue.svg");
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
}

.border-gradient {
  border: 5px solid transparent;
  border-image: linear-gradient(to right, #000, #fff) 1;
}
</style>
